﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using TTData;
using TTMain.Data;

namespace TTMain.Core
{
    public class GameCore
    {        

        private MapObjects _mapObj = null;
        private List<Player> _players = null;
        private Int32 _playerState;
        private Random _random = null;
        

        private String[] _cities = { City.AUGSBURG, City.BASEL, City.BUDWEIS, City.CARLSRUHE, City.FREIBURG, City.INGOLSTADT, 
                                  City.INNSBRUCK, City.KEMPTEN, City.LINZ, City.LODZ, City.MANNHEIM, City.MUNCHEN, City.NURENBERG, 
                                  City.PASSAU, City.PILSEN, City.REGENSBURG, City.SALZBURG, City.SIGMARINGEN, City.STUTTGART, 
                                  City.ULM, City.WURZBURG, City.ZURICH };
        private String[] _houseColors = { House.COLOR_BLUE, House.COLOR_GREEN, House.COLOR_RED, House.COLOR_YELLOW };
        
        
        /// <summary>
        /// Creates a new Game Core object which hold all the information about the game in play
        /// </summary>
        /// <param name="numberOfPlayers">the number of players in the game</param>
        /// <param name="players">the list of players in the game</param>
        /// <param name="initial6Cards">the initial 6 cards that are visible on the game board</param>
        public GameCore(Int32 numberOfPlayers, List<Player> players, List<CityCard> initial6Cards)
        {
            _mapObj = new MapObjects(numberOfPlayers);
            _players = new List<Player>();
            _random = new Random();

            for (int i = 0; i < players.Count; i++)
                _players.Add(players[i]);

            for (int i = 0; i < initial6Cards.Count; i++)
            {

                CityCard c = GetNextCityCard(initial6Cards[i].CityName);
                RemoveCardFromStack(initial6Cards[i].CityName);
                _mapObj.DisplayCardList.Add(c);
            }
        }

        public void StartTurn(String nickname)
        {
            Player p = GetPlayerByNickname(nickname);
            if (p.PrivateCards.Count == 0)
                _playerState = 1;
            else
                _playerState = 6;
        }

        public void ScoreHelp(String nickname)
        {
            Player p = GetPlayerByNickname(nickname);
        }


        /// <summary>
        /// Calculates all the current moves available for a user
        /// </summary>
        /// <param name="nickname">the nickname of the user</param>
        /// <returns>an array of move constants</returns>
        public ArrayList GetAvailableMoves(String nickname)
        {
            Player p; 
            ArrayList _result = new ArrayList();

            switch (_playerState)
            {
                case 1:
                    _result.Add(MoveConstants.TAKE_CARD);
                    _result.Add(MoveConstants.USE_POSTMASTER);
                    break;
                case 2:
                    _result.Add(MoveConstants.TAKE_CARD);
                    _result.Add(MoveConstants.USE_POSTMASTER);
                    break;
                case 3:
                    _result.Add(MoveConstants.PUT_CARD);
                    break;
                case 4:
                    _result.Add(MoveConstants.END_TURN);
                    p = GetPlayerByNickname(nickname);
                    if (p.PublicCards.Count >= 3)
                        _result.Add(MoveConstants.CLOSE_AND_SCORE_ROUTE);
                    break;
                case 6:
                    _result.Add(MoveConstants.USE_ADMINISTRATOR);
                    _result.Add(MoveConstants.TAKE_CARD);
                    _result.Add(MoveConstants.USE_POSTMASTER);
                    break;
                case 7:
                    _result.Add(MoveConstants.TAKE_CARD);
                    break;
                case 8:
                    _result.Add(MoveConstants.PUT_CARD);
                    break;
                case 9:
                    _result.Add(MoveConstants.END_TURN);
                    p = GetPlayerByNickname(nickname);
                    if (p.PublicCards.Count > 2)
                        _result.Add(MoveConstants.CLOSE_AND_SCORE_ROUTE);
                    break;
                case 15:
                    _result.Add(MoveConstants.TAKE_CARD);
                    _result.Add(MoveConstants.USE_POSTMASTER);
                    _result.Add(MoveConstants.PUT_CARD);
                    _result.Add(MoveConstants.USE_POSTAL_CARRIER);
                    break;
                case 16:
                    _result.Add(MoveConstants.PUT_CARD);
                    break;
                case 18:
                    _result.Add(MoveConstants.PUT_CARD);
                    _result.Add(MoveConstants.USE_POSTAL_CARRIER);
                    p = GetPlayerByNickname(nickname);

                    if (p.CarrigeCard.Value >= 3)
                    {
                        if ((p.PublicCards.Count + 2) >= p.CarrigeCard.Value +1)
                            _result.Add(MoveConstants.USE_CARTWRIGHT);
                    }

                    _result.Add(MoveConstants.TAKE_CARD);
                    _result.Add(MoveConstants.USE_POSTMASTER);
                    _result.Add(MoveConstants.END_TURN);
                    p = GetPlayerByNickname(nickname);
                   if (p.PublicCards.Count > 2)
                        _result.Add(MoveConstants.CLOSE_AND_SCORE_ROUTE);
                    break;
                case 19:
                    _result.Add(MoveConstants.PUT_CARD);
                    _result.Add(MoveConstants.USE_POSTAL_CARRIER);
                    break;
            }

            return _result;
        }

        /// <summary>
        /// Notifies that a user has taken one of the 6 display cards
        /// </summary>
        /// <param name="nickname">the nickname of the user</param>
        /// <param name="position">a 0-5 value representing the index of the card drawn</param>
        /// <returns>a new card from the stack to replace the old one</returns>
        public void TakeCardDisplay(String nickname, Int32 position, CityCard nextCard)
        {
            Player p = GetPlayerByNickname(nickname);
            CityCard c = (CityCard)_mapObj.DisplayCardList[position];
            p.PrivateCards.Add(c);
            RemoveCardFromStack(nextCard.CityName);
            _mapObj.DisplayCardList[position] = nextCard;

            switch (_playerState)
            {
                case 1:
                    _playerState = 2;
                    break;
                case 2:
                    _playerState = 3;
                    break;
                case 6:
                    _playerState = 15;
                    break;
                case 7:
                    _playerState = 8;
                    break;
                case 15:
                    _playerState = 16;
                    break;
                case 18:
                    _playerState = 9;
                    break;
            }
        }

        public void TakeCardDisplay(String nickname, Int32 position, String nextCardName)
        {
            Player p = GetPlayerByNickname(nickname);

            if ((position >= 0) && (position < 6))
            {
                CityCard c = (CityCard)_mapObj.DisplayCardList[position];
                if (c != null)
                {
                    p.PrivateCards.Add(c);
                    CityCard card = GetNextCityCard(nextCardName);
                    if (card != null)
                    {
                        RemoveCardFromStack(card.CityName);

                        _mapObj.DisplayCardList[position] = card;

                        switch (_playerState)
                        {
                            case 1:
                                _playerState = 2;
                                break;
                            case 2:
                                _playerState = 3;
                                break;
                            case 6:
                                _playerState = 15;
                                break;
                            case 7:
                                _playerState = 8;
                                break;
                            case 15:
                                _playerState = 16;
                                break;
                            case 18:
                                _playerState = 9;
                                break;
                        }
                    }
                }
            }
        }

        /// <summary>
        /// Notifies that a user has taken a card from the stack
        /// </summary>
        /// <param name="nickname">the nickname of the user</param>
        /// <returns>the card which was drawn from the stack</returns>      
        public void TakeCardSupply(String nickname, CityCard card)
        {            
            Player p = GetPlayerByNickname(nickname);
            p.PrivateCards.Add(card);
            RemoveCardFromStack(card.CityName);

            switch (_playerState)
            {
                case 1:
                    _playerState = 2;
                    break;
                case 2:
                    _playerState = 3;
                    break;
                case 6:
                    _playerState = 15;
                    break;
                case 7:
                    _playerState = 8;
                    break;
                case 15:
                    _playerState = 16;
                    break;
            }
        }

        public void TakeCardSupply(String nickname, String cardName)
        {
            Player p = GetPlayerByNickname(nickname);
            CityCard card = GetNextCityCard(cardName);

            p.PrivateCards.Add(card);
            RemoveCardFromStack(card.CityName);

            switch (_playerState)
            {
                case 1:
                    _playerState = 2;
                    break;
                case 2:
                    _playerState = 3;
                    break;
                case 6:
                    _playerState = 15;
                    break;
                case 7:
                    _playerState = 8;
                    break;
                case 15:
                    _playerState = 16;
                    break;
            }
        }

        public void PutCard(String nickname, CityCard card, Int16 position)
        {
            Player p = GetPlayerByNickname(nickname);
            p.PrivateCards.Remove(card);

            if (position == 0)
                p.PublicCards.Insert(0, card);
            else
                p.PublicCards.Add(card);

            switch (_playerState)
            {
                case 3:
                    _playerState = 4;
                    break;
                case 8:
                    _playerState = 9;
                    break;
                case 15:
                    _playerState = 18;
                    break;
                case 18:
                    _playerState = 9;
                    break;
                case 16:
                    _playerState = 9;
                    break;
            }
        }

        public void PutCard(String nickname, String cardName, Int16 position)
        {
            Player p = GetPlayerByNickname(nickname);
            CityCard card = null;

            for (int i = 0; i < p.PrivateCards.Count; i++)
            {
                card = (CityCard)p.PrivateCards[i];
                if (card.CityName.Equals(cardName))
                    break;
            }

            if (card != null)
            {

                p.PrivateCards.Remove(card);

                if (position == 0)
                    p.PublicCards.Insert(0, card);
                else
                    p.PublicCards.Add(card);

                switch (_playerState)
                {
                    case 3:
                        _playerState = 4;
                        break;
                    case 8:
                        _playerState = 9;
                        break;
                    case 15:
                        _playerState = 18;
                        break;
                    case 18:
                        _playerState = 9;
                        break;
                    case 16:
                        _playerState = 9;
                        break;
                }
            }
        }

        public void PutHouses(String nickname, List<String> cities)
        {   
            Player p = GetPlayerByNickname(nickname);

            for (int i = 0; i < cities.Count; i++)
            {
                House house = new House(cities[i], p.HouseColor);
                p.Houses.Add(house);
            }

            for (int i = 0; i < p.PublicCards.Count; i++)
            {
                CityCard c = (CityCard)p.PublicCards[i];
                _mapObj.DiscardedCardList.Add(c);
            }
            p.PublicCards.Clear();

        }

        public void DiscardPublicCards(String nickname)
        {
            Player p = GetPlayerByNickname(nickname);

            if (p != null)
            {
                for (int i = 0; i < p.PublicCards.Count; i++)
                {
                    CityCard c = (CityCard)p.PublicCards[i];
                    _mapObj.DiscardedCardList.Add(c);
                }
                p.PublicCards.Clear();
            }

        }

        public void DiscardPrivateCards(String nickname)
        {
            Player p = GetPlayerByNickname(nickname);

            for (int i = 0; i < p.PrivateCards.Count; i++)
            {
                CityCard c = (CityCard)p.PrivateCards[i];
                _mapObj.DiscardedCardList.Add(c);
            }
            p.PrivateCards.Clear();
        }

        public void DiscardPrivateCards(String nickname, List<CityCard> cardsList)
        {
            Player p = GetPlayerByNickname(nickname);

            for (int i = 0; i < cardsList.Count; i++)
            {
                int index = p.PrivateCards.IndexOf(cardsList[i]);
                if (index != -1)
                {
                    p.PrivateCards.RemoveAt(i);
                    _mapObj.DiscardedCardList.Add(cardsList[i]);
                }
            }
        }

        public void DiscardPrivateCards(String nickname, List<String> cardNamesList)
        {
            Player p = GetPlayerByNickname(nickname);

            for (int i = 0; i < cardNamesList.Count; i++)
            {

                for (int j = 0; j < p.PrivateCards.Count; j++)
                {
                    CityCard c = (CityCard)p.PrivateCards[j];
                    if (c.CityName.Equals(cardNamesList[i]))
                    {
                        p.PrivateCards.RemoveAt(j);
                        _mapObj.DiscardedCardList.Add(c);
                        break;
                    }
                }
            }
        }

        public void UseAdministrator(List<CityCard> cards)
        {
            for (int i = 0; i < cards.Count; i++)
            {
                _mapObj.DiscardedCardList.Add(_mapObj.DisplayCardList[i]);
                _mapObj.DisplayCardList[i] = cards[i];
                RemoveCardFromStack(cards[i].CityName);
            }

            if (_playerState == 6)
                _playerState = 7;
        }
        
        public List<CityCard> GetAdministrator6Cards()
        {
            List<CityCard> _result = new List<CityCard>();

            if (_mapObj.CityCardList.Count < 6)
            {
                for (int i = 0; i < _mapObj.CityCardList.Count; i++)
                {
                    CityCard c = (CityCard)_mapObj.CityCardList[i];
                    _result.Add(c);
                }
                for (int i = 0; i < 6 - _result.Count; i++ )
                {
                    int r = _random.Next(0, _mapObj.DiscardedCardList.Count);
                    CityCard c = (CityCard)_mapObj.DiscardedCardList[r];
                    _result.Add(c);
                }

                return _result;
            }
            else
                for (int i = 0; i < 6; i++)
                {
                    CityCard c = GetNextCityCard();
                    _result.Add(c);
                }
            return _result;
        }

        public List<String> GetCitiesForHouses(String nickname)
        {
            Player p = GetPlayerByNickname(nickname);
            List<String> result = new List<String>();

            for (int i = 0; i < p.PublicCards.Count; i++)
            {
                if (!HasCityHouse(p, ((CityCard)p.PublicCards[i]).CityName))
                    result.Add(((CityCard)p.PublicCards[i]).CityName);
            }

            return result;
        }

        public List<String> GetCitiesForHouses(String nickname, List<String> cityNames)
        {
            Player p = GetPlayerByNickname(nickname);
            List<String> result = new List<String>();

            if (cityNames.Count < 2)
            {
                for (int i = 0; i < p.PublicCards.Count; i++)
                {
                    if (!HasCityHouse(p, ((CityCard)p.PublicCards[i]).CityName))
                        result.Add(((CityCard)p.PublicCards[i]).CityName);
                }
            }
            else
            {
                List<String> _regions = new List<String>();

                for (int i = 0; i < cityNames.Count; i++)
                    _regions.Add(City.GetCityRegion(cityNames[i]));

                if (_regions[0] == _regions[1])
                {
                    for (int i = 0; i < p.PublicCards.Count; i++)
                    {
                        if (_regions[0].Equals(City.GetCityRegion(((CityCard)p.PublicCards[i]).CityName)))
                            if (!HasCityHouse(p, ((CityCard)p.PublicCards[i]).CityName))
                                result.Add(((CityCard)p.PublicCards[i]).CityName);
                    }
                }
                else
                {
                    for (int i = 0; i < cityNames.Count; i++)
                        result.Add(cityNames[i]);


                    for (int i = 0; i < p.PublicCards.Count; i++)
                    {
                        Boolean isSameRegion = false;
                        for (int j = 0; j < _regions.Count; j++)
                        {
                            String auxRegion = City.GetCityRegion(((CityCard)p.PublicCards[i]).CityName);
                            if (auxRegion.Equals(_regions[j]))
                            {
                                isSameRegion = true;
                                break;
                            }
                        }
                        if (!isSameRegion)
                            if (!HasCityHouse(p, ((CityCard)p.PublicCards[i]).CityName))
                                result.Add(((CityCard)p.PublicCards[i]).CityName);

                    }
                }

            }

            return result;
        }

        public CityCard GetNextCityCard()
        {
            if (_mapObj.CityCardList.Count == 0)
            {
                for (int i = 0; i < _mapObj.DiscardedCardList.Count; i++)
                    _mapObj.CityCardList.Add(_mapObj.DiscardedCardList[i]);
                _mapObj.DiscardedCardList.Clear();
            }
            
            int r = _random.Next(0, _mapObj.CityCardList.Count);
            CityCard c = (CityCard)_mapObj.CityCardList[r];
            return c;
        }

        public CityCard GetNextCityCard(String cityName)
        {            
            if (_mapObj.CityCardList.Count == 0)
            {
                for (int i = 0; i < _mapObj.DiscardedCardList.Count; i++)
                    _mapObj.CityCardList.Add(_mapObj.DiscardedCardList[i]);
                _mapObj.DiscardedCardList.Clear();
            }


            for (int i = 0; i < _mapObj.CityCardList.Count; i++)
                if (((CityCard)_mapObj.CityCardList[i]).CityName.Equals(cityName))
                {
                    CityCard c = (CityCard)_mapObj.CityCardList[i];                    
                    return c;
                }

            for (int i = 0; i < _mapObj.DiscardedCardList.Count; i++)
                _mapObj.CityCardList.Add(_mapObj.DiscardedCardList[i]);
            _mapObj.DiscardedCardList.Clear();

            for (int i = 0; i < _mapObj.CityCardList.Count; i++)
                if (((CityCard)_mapObj.CityCardList[i]).CityName.Equals(cityName))
                {
                    CityCard c = (CityCard)_mapObj.CityCardList[i];
                    return c;
                }

            return null;
        }

        /// <summary>
        /// Retrives the display card found on the position specified
        /// </summary>
        /// <param name="position">the position</param>
        /// <returns>the card on the position</returns>
        public CityCard GetDisplayCard(int position)
        {
            CityCard c = (CityCard)_mapObj.DisplayCardList[position];
            return c;
        }

        public String GetPlayerColor(String nickname)
        {
            Player p = GetPlayerByNickname(nickname);
            if (p != null)
                return p.HouseColor;
            return null;
        }

        public Int32 GetCardPutPosition(String nickname, CityCard card)
        {
            Player p = GetPlayerByNickname(nickname);

            if (p.PublicCards.Count == 0)
                return MoveConstants.POSITION_LEFT_ONLY;

            for (int i = 0; i < p.PublicCards.Count; i++)
            {
                CityCard c = (CityCard)p.PublicCards[i];
                if (card.CityName.Equals(c.CityName))
                    return MoveConstants.POSITION_NONE;
            }

            CityCard leftCard = (CityCard)p.PublicCards[0];
            CityCard rightCard = (CityCard)p.PublicCards[p.PublicCards.Count - 1];

            Boolean isLeftAdiacent = AreCitiesAdjacent(leftCard, card);
            Boolean isRightAdiacent = AreCitiesAdjacent(rightCard, card);

            if (isLeftAdiacent && isRightAdiacent)
                return MoveConstants.POSITION_BOTH;
            if (isLeftAdiacent)
                return MoveConstants.POSITION_LEFT_ONLY;
            if (isRightAdiacent)
                return MoveConstants.POSITION_RIGHT_ONLY;

            return MoveConstants.POSITION_NONE;

        }

        private Player GetPlayerByNickname(String nickname)
        {
            Player p = null;
            for (int i = 0; i < _players.Count; i++)
            {
                p = (Player)_players[i];
                if (p.Nickname.Equals(nickname))
                    return p;
            }
            return null;
        }

        private void UseScoreHelp(String nickname)
        {

        }

        private void RemoveCardFromStack(String cityName)
        {
            for (int i = 0; i < _mapObj.CityCardList.Count; i++)
                if (((CityCard)_mapObj.CityCardList[i]).CityName.Equals(cityName))
                {
                    CityCard c = (CityCard)_mapObj.CityCardList[i];
                    _mapObj.CityCardList.RemoveAt(i);
                    return;
                }
            return; 
        }

        /// <summary>
        /// Check to see if two cities have a direct connection
        /// </summary>
        /// <param name="a">the first city</param>
        /// <param name="b">the second city</param>
        /// <returns>true if the two cities are connected, false otherwise</returns>
        private Boolean AreCitiesAdjacent(CityCard a, CityCard b)
        {
            int i, j;

            for (i = 0; i < 22; i++)
            {
                if (a.CityName.Equals(_cities[i]))
                    break;
            }

            for (j = 0; j < 22; j++)
            {
                if (b.CityName.Equals(_cities[j]))
                    break;
            }

            if (_mapObj.Matrix[i, j] == 1)
                return true;
            else
                return false;
        }

        private Boolean HasCityHouse(Player player, String cityName)
        {
            for (int i = 0; i < player.Houses.Count; i++)
            {
                House h = (House)player.Houses[i];
                if (h.CityName.Equals(cityName))
                    return true;
            }
            return false;
        }

        #region Bonuses and Carrige Cards

        public BonusCard GetRoadLengthBonus(String nickname)
        {
            Player p = GetPlayerByNickname(nickname);

            if (p.PublicCards.Count == 7)
            {
                BonusCard c = _mapObj.ExtractBonusCard(BonusCard.BONUS_ROAD_LENGTH_7);
                if (c != null)
                {
                    p.Bonuses.Add(c);
                    return c;
                }

            }
            else if (p.PublicCards.Count == 6)
            {
                BonusCard c = _mapObj.ExtractBonusCard(BonusCard.BONUS_ROAD_LENGTH_6);
                if (c != null)
                {
                    p.Bonuses.Add(c);
                    return c;
                }
            }
            else if (p.PublicCards.Count == 5)
            {
                BonusCard c = _mapObj.ExtractBonusCard(BonusCard.BONUS_ROAD_LENGTH_5);
                if (c != null)
                {
                    p.Bonuses.Add(c);
                    return c;
                }
            }

            return null;
        }

        public BonusCard GetCurrentBonusCard(Int32 bonusType)
        {
            return _mapObj.GetBonusCard(bonusType);
        }

        public CarrigeCard GetCarrigeCard(String nickname)
        {
            Player p = GetPlayerByNickname(nickname);
            if (p.CarrigeCard == null)
                p.CarrigeCard = new CarrigeCard(2, 0);
            
            int value = p.CarrigeCard.Value + 1;
            if (p.PublicCards.Count >= value)
            {
                CarrigeCard c = _mapObj.ExtractCarrigeCard(value);
                p.CarrigeCard = c;
                return c;
            }
            return null;
        }

        public CarrigeCard GetCarrigeCardWithHelp(String nickname)
        {
            Player p = GetPlayerByNickname(nickname);
            if (p.CarrigeCard == null)
                p.CarrigeCard = new CarrigeCard(2, 0);

            if (p.CarrigeCard.Value > 2)
            {

                int value = p.CarrigeCard.Value + 1;
                if ((p.PublicCards.Count + 2) >= value)
                {
                    CarrigeCard c = _mapObj.ExtractCarrigeCard(value);
                    p.CarrigeCard = c;
                    return c;
                }
            }
            return null;
        }

        public CarrigeCard GetCurrentCarrigeCard(Int32 value)
        {
            return _mapObj.GetCarrigeCard(value);
        }

        public BonusCard GetAllRegionsBonus(String nickname)
        {
            Player p = GetPlayerByNickname(nickname);
            if (p.HasBonus(BonusCard.BONUS_REGION_ALL))
                return null;

            List<String> regionsWithHouse = new List<String>();

            for (int i = 0; i < p.Houses.Count; i++)
            {
                String city = p.Houses[i].CityName;
                String region = City.GetCityRegion(city);
                if (regionsWithHouse.IndexOf(region) == -1)
                    regionsWithHouse.Add(region);
            }
            if (regionsWithHouse.Count == Region.REGIONS_COUNT)
            {
                BonusCard bCard = _mapObj.ExtractBonusCard(BonusCard.BONUS_REGION_ALL);
                if (bCard != null)                
                    p.Bonuses.Add(bCard);                
                return bCard;
            }
            return null;
        }

        public BonusCard GetRegionBonus(String nickname, Int32 bonusRegion)
        {
            

            Player p = GetPlayerByNickname(nickname);
            int cityCount = 0;
            String regionName = "";
            String regionName2 = "";

            if (p.HasBonus(bonusRegion))
                return null;

            if ((bonusRegion == BonusCard.BONUS_REGION_BADEN) || (bonusRegion == BonusCard.BONUS_REGION_BAIERN))
            {
                if (bonusRegion == BonusCard.BONUS_REGION_BADEN)
                    regionName = Region.BADEN;
                else
                    regionName = Region.BAIERN;
                for (int i = 0; i < p.Houses.Count; i++)
                {
                    String city = p.Houses[i].CityName;
                    String region = City.GetCityRegion(city);
                    if (region.Equals(regionName))
                        cityCount++;
                }
                if (cityCount == Region.GetRegionCitiesCount(regionName))
                {
                    BonusCard bCard = _mapObj.ExtractBonusCard(bonusRegion);
                    if (bCard != null)
                        p.Bonuses.Add(bCard);
                    return bCard;
                }
            }
            else
            {
                if (bonusRegion == BonusCard.BONUS_REGION_BOHEM_SALZB)
                {
                    regionName = Region.BOHMEN;
                    regionName2 = Region.SALZBURG;
                }
                else if (bonusRegion == BonusCard.BONUS_REGION_SCHWEIZ_TYROL)
                {
                    regionName = Region.SCHWEIZ;
                    regionName2 = Region.TYROI;
                }
                else if (bonusRegion == BonusCard.BONUS_REGION_WURTT_HOHENZ)
                {
                    regionName = Region.WURTTEMBERG;
                    regionName2 = Region.HOHENZOLLERN;
                }
                for (int i = 0; i < p.Houses.Count; i++)
                {
                    String city = p.Houses[i].CityName;
                    String region = City.GetCityRegion(city);
                    if (region.Equals(regionName) || region.Equals(regionName2))
                        cityCount++;
                }
                if (cityCount == (Region.GetRegionCitiesCount(regionName) + Region.GetRegionCitiesCount(regionName2)))
                {
                    BonusCard bCard = _mapObj.ExtractBonusCard(bonusRegion);
                    if (bCard != null)
                        p.Bonuses.Add(bCard);
                    return bCard;
                }
            }

            return null;

        }

        public BonusCard GetEndBonus(String nickname)
        {
            Player p = GetPlayerByNickname(nickname);            
                       
            if ((p.Houses.Count >= 20) || (p.CarrigeCard.Value == 7))
            {
                BonusCard bCard = _mapObj.ExtractBonusCard(BonusCard.BONUS_FINISH_GAME);
                p.Bonuses.Add(bCard);
                return bCard;
            }
            return null;
        }

        #endregion

        public List<Player> GetPlayerList()
        {
            return _players;
        }

        
    }
}
